#include <iostream>
#include <memory>

using std::cout;
using std::endl;
using std::ostream;

class Point
{
public:
    /* explicit */
    Point(int ix = 0, int iy = 0)
    : _ix(ix), _iy(iy)
    {
        cout << "Point(int=0,int=0)" << endl;
    }

    ~Point() {  cout << "~Point()" << endl; }

    friend ostream & operator<<(ostream & os, const Point &rhs);

private:
    int _ix;
    int _iy;
};

ostream & operator<<(ostream & os, const Point &rhs)
{
    os << "(" << rhs._ix
       << "," << rhs._iy
       << ")";
    return os; 
}

template <class T>
class MyVector
{
public:
    MyVector()
    : _start(nullptr)
    , _finish(nullptr)
    , _end_of_storage(nullptr)
    {}

    ~MyVector()
    {
        //先销毁空间中的数据
        while(_start != _finish) {
            _alloc.destroy(--_finish);
        }
        //释放堆空间
        _alloc.deallocate(_start, capacity());
    }

    int size() const
    {   return _finish - _start;   }

    int capacity() const 
    {   return _end_of_storage - _start;    }

    T * begin() 
    {   return _start;  }

    T * end()
    {   return _finish; }

    void push_back(const T & t)
    {
        if(size() == capacity()) {
            //动态扩容
            reallocate();
        }
        //有空间的情况下,就要在_finish位置上构建对象
        _alloc.construct(_finish, t);
        ++_finish;
    }

    void pop_back()
    {
        if(size() > 0) {
            //删除尾部的元素
            _alloc.destroy(--_finish);
        }
    }
private:
    void reallocate()//重新分配内存，动态扩容时使用
    {
        int oldCapacity = capacity();
        int newCapacity = (oldCapacity > 0 ? 2 * oldCapacity : 1);
        //申请新的空间
        T * ptmp = _alloc.allocate(newCapacity);
        //将原空间中的数据拷贝到新的空间
        if(_start) {
            //要求新旧空间上都要存在对象, 而ptmp所指空间上还没有对象
            //不能使用std::copy完成对象的复制
            //std::copy(_start, _finish, ptmp);
            //在未初始化空间上复制对象
            std::uninitialized_copy(_start, _finish, ptmp);
            //销毁原空间中的数据
            while(_start != _finish) {
                _alloc.destroy(--_finish);
            }
            //释放原空间
            _alloc.deallocate(_start, oldCapacity);
        }
        //改变三个指针的位置
        _start = ptmp;
        _finish = _start + oldCapacity;
        _end_of_storage = _start + newCapacity;
    }

private:
    //_alloc进行内存管理
    static std::allocator<T> _alloc;
    T * _start;
    T * _finish;
    T * _end_of_storage;
};

//静态数据成员要在类之外初始化
template <class T>
std::allocator<T> MyVector<T>::_alloc;


int test0()
{
    MyVector<int> numbers;
    numbers.push_back(1);
    cout << "numbers' size:" << numbers.size() << endl;
    cout << "numbers' capacity:" << numbers.capacity() << endl;
    numbers.push_back(1);
    cout << "numbers' size:" << numbers.size() << endl;
    cout << "numbers' capacity:" << numbers.capacity() << endl;
    numbers.push_back(1);
    cout << "numbers' size:" << numbers.size() << endl;
    cout << "numbers' capacity:" << numbers.capacity() << endl;
    numbers.push_back(1);
    cout << "numbers' size:" << numbers.size() << endl;
    cout << "numbers' capacity:" << numbers.capacity() << endl;
    numbers.push_back(1);
    cout << "numbers' size:" << numbers.size() << endl;
    cout << "numbers' capacity:" << numbers.capacity() << endl;

    //增强for循环要求类中必须提供begin和end函数
    for(auto & e : numbers) {
        cout << e << " ";
    }
    cout << endl;

    return 0;
}

void test1()
{
    MyVector<Point> numbers;
    numbers.push_back(1);
    cout << "numbers' size:" << numbers.size() << endl;
    cout << "numbers' capacity:" << numbers.capacity() << endl;
    numbers.push_back(1);
    cout << "numbers' size:" << numbers.size() << endl;
    cout << "numbers' capacity:" << numbers.capacity() << endl;
    numbers.push_back(1);
    cout << "numbers' size:" << numbers.size() << endl;
    cout << "numbers' capacity:" << numbers.capacity() << endl;
    numbers.push_back(1);
    cout << "numbers' size:" << numbers.size() << endl;
    cout << "numbers' capacity:" << numbers.capacity() << endl;
    numbers.push_back(1);
    cout << "numbers' size:" << numbers.size() << endl;
    cout << "numbers' capacity:" << numbers.capacity() << endl;

    //增强for循环要求类中必须提供begin和end函数
    for(auto & e : numbers) {
        cout << e << " ";
    }
    cout << endl;
}

int main()
{
    test1();
}

